(function(layui) {
  'use strict';

  /**
   * @typedef {ArrayLike} jQuery
   */

  var MODULE_NAME = 'proGridForm';

  function execute(input) {
    var data;
    try {
      data = new Function('return ' + input)();
    } catch (e) {
      data = input;
    }
    return data;
  }

  layui.extend({
    'ResizeDetector': './lib/resize-detector'
  }).define(['jquery', 'laytpl', 'ResizeDetector'], function(exports) {
    var $ = layui.jquery;
    var laytpl = layui.laytpl;
    var form = layui.form;
    // var ResizeDetector = layui.ResizeDetector;

    /**
     * 获取全局配置，默认只提取以下属性
     * - searchText
     * - resetText
     * - reverse
     */
    var LayuiGlobalOptions = (window.LAYUI_GLOBAL || {}).gridForm || {};
    var globalSearchText = LayuiGlobalOptions.searchText || '查询';
    var globalResetText = LayuiGlobalOptions.resetText || '重置';
    var globalReverse = LayuiGlobalOptions.reverse || false;
    var globalUseCard = LayuiGlobalOptions.useCard || true;

    /**
     * 渲染表格查询区域
     * @param {Object} options
     * @param {string|HTMLElement|jQuery} options.el 挂载的 dom 对象
     * @param {boolean} options.useCard 外部是否用 layui-card 包裹
     * @param {string} options.searchText 查询按钮的文字，默认是 查询，可在全局配置LAYUI_GLOBAL的tableSearch下配置
     * @param {string} options.resetText 重置按钮的文字，默认是 重置，可在全局配置LAYUI_GLOBAL的tableSearch下配置
     * @param {boolean} options.reverse 是否将按钮反向排版，默认重置在左，查询在右，可在全局配置LAYUI_GLOBAL的tableSearch下配置
     * @param {Function} options.success 渲染成功的回调
     * @param {Function} options.search 查询按钮的回调
     * @param {Function} options.reset 重置按钮的回调
     */
    var renderHandler = function(options) {
      /**
       * 默认配置
       * @type {typeof options}
       */
      var defaultOptions = {
        el        : null,
        useCard   : globalUseCard,
        searchText: globalSearchText,
        resetText : globalResetText,
        reverse   : globalReverse,
        // callback
        success   : null,
        search    : null,
        reset     : null
      };

      // 合并配置
      var mergedOptions = $.extend({}, defaultOptions, options);
      // 只匹配第一符合的 dom
      var $template = $(mergedOptions.el).eq(0);
      // 如果找到符合项隐藏它，反之结束渲染
      if ($template.length) $template.addClass('layui-hide');
      else return;

      var domTemplate = $template[0];
      // 判断是不是 template 标签，这个需要特殊处理
      var isTemplateElement = domTemplate.tagName === 'TEMPLATE' && domTemplate.nodeType === 1;
      var $target = isTemplateElement
        ? $(domTemplate.content.querySelector('lay-form'))
        : $($template.html()).eq(0); // 考虑到有的使用了 script 标签

      doRender($template, $target, mergedOptions, function(html) {
        // 将渲染好的代码添加模板之后
        $template.after(html);
        // 渲染表单中的选择框
        form.render('select');
        // 找到渲染后的模板对象
        var $rendered = $template.next();

        callHooks(mergedOptions, $rendered);

        // ResizeDetector.addResizeListener($rendered[0], function() {
        //   var $form = $rendered.find('.layui-form');
        //   var width = $form.width();
        //   var html = [
        //     '<div class="layui-row">',
        //     renderItems($target, width),
        //     renderActions(mergedOptions, width),
        //     '</div>'
        //   ].join('');
        //   $form.html(html);
        //   form.render('select');
        //   callHooks(mergedOptions, $rendered);
        // });
      });
    };

    exports(MODULE_NAME, {
      render: renderHandler
    });

    function doRender($template, $target, options, callback) {
      if (!$template.length || !$target.length) return;

      $.when(
        $.ajax({
          url     : layui.setter.base + './lib/components/templates/form-item.html',
          type    : 'get',
          dataType: 'html'
        }),
        $.get({
          url     : layui.setter.base + './lib/components/templates/form.html',
          type    : 'get',
          dataType: 'html'
        })
      ).done(function(formItemTpl, formTpl) {
        formItemTpl = formItemTpl[0];
        formTpl = formTpl[0];
        $template.after('<div />');
        var $test = $template.next();
        var wrapperWidth = $test.width();
        $test.remove();

        var html = laytpl(formTpl).render({
          useCard  : options.useCard,
          className: $target.attr('class'),
          style    : $target.attr('style'),
          filter   : execute($target.attr('lay-filter')),
          content  : generateFormItemHtml($target, formItemTpl, wrapperWidth, {
            shouldRenderCollapse: options.shouldRenderCollapse,
            isCollapse          : options.actionsCollapse,
            render              : !!options.customRenderActions,
            customRender        : options.customRenderActions,
            reverse             : options.reverse,
            searchText          : options.searchText,
            resetText           : options.resetText
          })
        });

        callback && callback(html);
      });
    }

    function callHooks(options, $scope) {
      // 调用成功钩子
      $.isFunction(options.success) && options.success($scope);
      // 如果存在 search 或 reset 方法，则渲染的按钮自动绑定事件
      if (
        $.isFunction(options.search) ||
        $.isFunction(options.reset)
      ) {
        $scope.find('button[data-action]').on('click', function() {
          var $this = $(this);
          var action = $this.data('action');
          action === 'search' && $.isFunction(options.search) && options.search.call(this, $scope);
          action === 'reset' && $.isFunction(options.reset) && options.reset.call(this, $scope);
        });
      }
    }

    function generateFormItemHtml($target, formItemTpl, wrapperWidth, actionsOptions) {
      var showItemLength = calcShowItemLength(wrapperWidth);
      var totalSpan = 0;
      var currentSpan = 0;
      var itemLength = 0;
      debugger;
      var html = $target.find('lay-form-item').map(function(i, item) {
        var $item = $(item);
        var raw = {};
        // lay-form-item 有效的参数
        'label,html-for,size,tips'.split(',').forEach(function(attr) {
          raw[$.camelCase(attr)] = execute($item.attr(attr));
        });

        var tips = $.type(raw.tips) === 'object'
          ? { icon: raw.tips.icon, content: raw.tips.content }
          : raw.tips == null ? false : { icon: 'about', content: raw.tips };

        var itemSize = raw.size || 1;
        var itemSpanOptions = generateFormItemSpan(itemSize, wrapperWidth);

        totalSpan += itemSpanOptions.totalSpan;

        var isHidden = actionsOptions.isCollapse && (
          !!i &&
          i > showItemLength - 1 &&
          totalSpan > 12
        );

        itemLength += 1;

        if (12 - (currentSpan % 12) < itemSpanOptions.totalSpan) {
          totalSpan += 12 - (currentSpan % 12);
          currentSpan += 12 - (currentSpan % 12);
        }

        currentSpan += itemSpanOptions.totalSpan;

        var formItemTplOptions = {
          className: isHidden ? 'layui-hide' : itemSpanOptions.className,
          label    : raw.label,
          htmlFor  : raw.htmlFor,
          content  : $item.html(),
          tips     : tips
        };

        return laytpl(formItemTpl).render(formItemTplOptions);
      }).join('');

      var shouldRenderCollapse = 'shouldRenderCollapse' in actionsOptions
        ? actionsOptions.shouldRenderCollapse
        : totalSpan >= 12 && itemLength >= showItemLength;

      var actionsOffset = 12 - itemSpanOptions.totalSpan - currentSpan % 12;

      if (actionsOptions.render) {
        var actionsHtmlList = [
          '<button class="layui-btn layui-btn-primary" type="button" data-action="reset">' + actionsOptions.resetText + '</button>',
          '<button class="layui-btn" type="button" data-action="search">' + actionsOptions.searchText + '</button>'
        ];
        var defaultActionsHtml = actionsOptions.reverse ? actionsHtmlList.reverse().join('') : actionsHtmlList.join('');
        var actionsOffsetClassName = actionsOffset ? ('layui-col-xs-offset' + actionsOffset) : '';
        var actionsContent = actionsOptions.customRender || defaultActionsHtml;

        shouldRenderCollapse && (
          actionsContent += '<a data-actions="collapse" data-collapse="' + !!actionsOptions.isCollapse + '">' + (actionsOptions.isCollapse ? '展开' : '收缩') + '</a>'
        );
        var actionsHtml = laytpl(formItemTpl).render({
          className: generateFormItemSpan(1, wrapperWidth).className + actionsOffsetClassName,
          content  : actionsContent
        });
        html += actionsHtml;
      }

      return html;
    }

    /**
     * 根据 lay-form-item 的位置返回对应的类名
     * @param {number} size lay-form-item 占用的位置
     * 一个 lay-form-item 临界值使用 110 + 220
     */
    function generateFormItemSpan(size, width) {
      if (!width) {
        return {
          className     : 'layui-hide',
          showItemLength: 0,
          singleSpan    : 0,
          totalSpan     : 0
        };
      }

      var MaxColumnNumber = 12;
      // 过滤
      var showItemLength = calcShowItemLength(width);
      var singleSpan = MaxColumnNumber / showItemLength;
      var totalSpan = Math.min(MaxColumnNumber, singleSpan * size);

      return {
        className     : 'layui-col-xs' + totalSpan,
        showItemLength: showItemLength,
        singleSpan    : singleSpan,
        totalSpan     : totalSpan
      };
    }

    function calcShowItemLength(width) {
      var ResponsiveColumns = [6, 4, 3, 2, 1];
      var ColumnWidthThreshold = 330;
      return Math.max.apply(Math, $.grep(ResponsiveColumns, function(span) {
        return (width / ColumnWidthThreshold) > span;
      }));
    }
  });
})(layui);
